#ifndef IO_H
#define IO_H

#include <QBitArray>
#include <QDebug>
#include <QObject>

#include "param.h"
#include "sensororder.h"
#include "serialportobj.h"
//#include "switch_forklift.h"

class IO : public QObject {
    Q_OBJECT
public:
    explicit IO( QObject* parent = nullptr );

#if FOKRLIFT_IO == FOKRLIFT_IO_OLD
    enum DiDefine {

        ACTIVATE = 0,              //（启动/暂停）按钮
        EMERGENCY_STOP,            //急停按钮
        RESET_BUTTON,              //复位按钮
        BUMPER_STRIP,              //防撞条
        LIFIT_UPPER_LIMIT,         //升降上限位
        LIFIT_DOWN_LIMIT,          //升降下限位
        DETECTION_ITEMS_LOCATION,  //货物到位检测
        LIFIT_MIDDLE_LIMIT,        //舵轮机械零点

        LEFT_OBSTACLE_SLOW_LAYER,         //左避障减速区域
        LEFT_OBSTACLE_STOP_LAYER,         //左避障急停区域
        RIGHT_OBSTACLE_SLOW_LAYER,        //右避障减速区域
        RIGHT_OBSTACLE_STOP_LAYER,        //右避障急停区域
        NAV_LASER_SLOW_LAYER,             //导航雷达减速区域
        NAV_LASER_STOP_LAYER,             //导航雷达急停区域
        FRONT_UPPER_OBSTACLE_STOP_LAYER,  //前上避障急停区域
        AUTO_MODE,                        //手自动切换

        LEFT_FORK_DETECTION,     //左货叉检测
        RIGHT_FORK_DETECTION,    //右货叉检测
        LEFT_PALLET_DETECTION,   //左托盘检测
        LEFT_GOODS_DETECTION,    //左货物检测
        RIGHT_PALLET_DETECTION,  //右托盘检测（无）
        RIGHT_GOODS_DETECTION,   //右货物检测（无）
        IN26,
        IN27,

        FORK_AUTO_MODE,    //叉车自动模式
        FORK_HANDLE_MODE,  //叉车手动模式
        IN32,
        IN33,
        IN34,
        IN35,
        IN36,
        IN37,
    };

    enum DoDefine {

        ACTIVATE_LED = 0,  //启动按钮指示灯
        CHARGE,            //充电继电器
        YELLOW_LED,        //三色灯黄色
        GREEN_LED,         //三色灯绿色
        RED_LED,           //三色灯红色
        OUT05,
        OUT06,
        OUT07,

        LEFT_OBSTACLE_INPUT_1,   //前左避障区域输入1
        LEFT_OBSTACLE_INPUT_2,   //前左避障区域输入2
        RIGHT_OBSTACLE_INPUT_1,  //前右避障区域输入1
        RIGHT_OBSTACLE_INPUT_2,  //前右避障区域输入2
        NAV_LASER_INPUT_1,       //导航雷达输入1
        NAV_LASER_INPUT_2,       //导航雷达输入2
        NAV_LASER_INPUT_3,       //导航雷达输入3
        OUT17,

        WORKING_MUSIC_1,  //语音播报1
        WORKING_MUSIC_2,  //语音播报2
        WORKING_MUSIC_3,  //语音播报3
        WORKING_MUSIC_4,  //语音播报4
        WORKING_MUSIC_5,  //语音播报5
        OUT25,
        OUT26,
        OUT27,

        OUT30,
        OUT31,
        OUT32,
        OUT33,
        OUT34,
        BACK_OBSTACLE_INPUT_1,  //后避障区域输入1（无）
        BACK_OBSTACLE_INPUT_2,  //后避障区域输入2（无）
        OUTLINE_LAMP,
    };

#endif

    enum IOState {
        SET = 0,
        RESET,
        TOGGLE,
    };

    enum IO_ADDRESS {
        IO_INPUT_1  = 1,  // IO输入模块1
        IO_OUTPUT_1 = 2,  // IO输出模块1
    };
    IOState getDi( DiDefine diIndex );              //公开输入io状态获取
    IOState getDo( DoDefine doIndex );              //公开输出io状态获取
    void setDo( DoDefine doIndex, IOState value );  //输出io状态设定
    void toggleDO( int id );                        //切换io状态
    void resetAllDo();                              //复位全部输出io,并选择是否关闭输出io的控制
    void breakHandler();                            //代码 崩溃失去控制而触发的特定io口
    void readIoState();
    void sendIoType();
    uint getIointputA();
    uint getIoOutput();

private:
    void       initData();                                //初始化数据
    QByteArray getIODataByAddress( IO_ADDRESS address );  //根据模块地址获取查询数据
    void ioControlSetIoState();                           //向io控制器发送命令设置输出io状态
    void ioSendData();

    SerialPortObj*       io_control_com = nullptr;  // IO模块串口
    QList< QByteArray >* sendDatas;                 //发送信息
    QBitArray            io_type_;                  // io的ui展示数目和类型
    QByteArray           GET_IO_INPUT_1;            //读取输入IO模块1
    QByteArray           SET_IO_OUTPUT_1;           //读取输出IO模块1

    unsigned int io_32in                   = 0x00000002;                         //输入IO控制器的io 32位
    unsigned int io_32out                  = 0x00000000;                         //输出IO控制器的io 32位
    int          input_1_lose_connect_time = 0, output_1_lose_connect_time = 0;  //失去连接时间
    int          sendIndex        = 0;                                           //发送信息下标
    bool         is_allow_setting = true;

signals:
    void sigSendData( SerialPortObj* obj, const QByteArray& data );
    void sigSendTips( const QString& );
    void sigLoseConnect( const QString& );
    void sigSendIoState( const QBitArray& );
    void sigSendIoType( const QBitArray& );
    void sigIOReceiveData( const QByteArray& data, const QString& str );  //测试,界面显示io接收源数据

public slots:
    void sltIOInit();
    void slt50msTimer();
    void sltIORecvieData( const QByteArray& data );
    void sltToggleDoBit( int moduleId, int id );
};

#endif  // IO_H
